<template>
  <WebGLCanvas :id="id"/>
</template>

<script setup lang="ts">
  import { Engine, Scene, ArcRotateCamera, Vector3,
    HemisphericLight, PointLight, MeshBuilder,
    StandardMaterial, Color3, Color4,
    Tools,
    Texture
  } from '@babylonjs/core'

  import Floor from '~/assets/images/babylon/village/floor.png'
  import Roof from '~/assets/images/babylon/village/roof.jpg'

  const id = 'build-a-village'
  useHead({
    title: '练习——建设一个村庄'
  })

  const initBabylon = () => {
    // 初始化canvas
    const canvas = document.querySelector<HTMLCanvasElement>(`#${id}`)
    if (!canvas) {
      throw new Error('Canvas not found.')
    }
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    // 初始化babylon 3D Engine, 开启抗锯齿
    /** 
     * “抗锯齿(英语:anti-aliasing,简称AA),
     * 也译为边缘柔化、消除混叠、抗图像折叠有损等。
     * 它是一种消除显示器输出的画面中图物边缘出现凹凸锯齿的技术,
     * 那些凹凸的锯齿通常因为高分辨率的信号以低分辨率表示或无法准确运算出3D图形坐标定位时所导致的图形混叠(aliasing)而产生的,
     * 反锯齿技术能有效地解决这些问题。
     */
    const engine = new Engine(canvas, true)

    // 创建一个场景
    const scene = new Scene(engine)
    scene.clearColor = new Color4(0, 0, 0, 1)
    // 添加一个相机
    const camera = new ArcRotateCamera(
      'camera',
      Tools.ToRadians(90),
      Tools.ToRadians(65),
      10,
      Vector3.Zero(),
      scene
    )
    // camera.position = new Vector3(0, 1, 10)
    // 绑定鼠标事件
    camera.attachControl(canvas, true)
    // 添加一组灯光到场景
    const light1 = new HemisphericLight('light1', new Vector3(5, 5, 0), scene)
    const light2 = new PointLight('light2', new Vector3(20, 20, 10), scene)
    light1.intensity = 1
    // 创建一个地面
    const ground = MeshBuilder.CreateGround('ground', {width: 10, height: 10}, scene)
    const groundMaterial = new StandardMaterial('groundMaterial', scene)
    groundMaterial.diffuseColor = new Color3(0.65, 0.48, 0.5)
    groundMaterial.diffuseTexture = new Texture(Floor, scene)
    ground.material = groundMaterial

    // 添加一个房子主体
    const box = MeshBuilder.CreateBox('box', {height: 1.6}, scene)
    const boxMaterial = new StandardMaterial('boxMaterial', scene)
    // boxMaterial.diffuseColor = new Color3(0.8, 0.65, 0.59)
    boxMaterial.diffuseTexture = new Texture(Floor, scene)
    box.material = boxMaterial
    box.position = new Vector3(0, 0.8, 0)

    // 添加一个房顶，利用圆柱体
    const cylinder = MeshBuilder.CreateCylinder(
      'cylinder',
      { diameter: 1.6, height: 1.6, tessellation: 3 },
      scene
    )
    const cylinderMaterial = new StandardMaterial('cylinderMaterial', scene)
    // cylinderMaterial.diffuseColor = new Color3(0.8, 0.25, 0.39)
    cylinderMaterial.diffuseTexture = new Texture(Roof, scene)
    cylinder.material = cylinderMaterial
    cylinder.rotation.z = Tools.ToRadians(90)
    cylinder.position = new Vector3(0, 2, 0)


    // 最后一步调用engine的runRenderLoop方案，
    // 执行scene.render()，让我们的3d场景渲染起来
    engine.runRenderLoop(() => {
      scene.render()
    })

    // 监听浏览器改变大小的事件，通过调用engine.resize()来自适应窗口大小
    window.addEventListener('resize', () => {
      engine.resize()
    })
  }

  onMounted(() => {
    initBabylon()
  })
</script>